function toUpper()
{
	iValue=$1

	oValue=`echo $iValue | tr '[a-z]' '[A-Z]'`	
	oValue=`echo $oValue | tr 'X' 'x'`
	
	echo $oValue
}

function toHex()
{
	iValue=$1
	oValue=`echo "obase=16; $iValue" | bc`

	oValue=`printf "%02x" "0x$oValue"`
	oValue=`toUpper $oValue`

	echo $oValue
}
  
function toHexStr()
{
	iValue=$1
	totLen=$2
	let "binTotLen = totLen * 8"

	ivBin=`echo "obase=2; $iValue" | bc`
	ivLen=`echo $ivBin | wc -c`
	let "ivLen = ivLen - 1"

	let "numPads = binTotLen - ivLen"
	let "limit = binTotLen - 8"

	pStr=""

	for i in `seq 1 $numPads`
	do
		pStr="0$pStr"
	done

	val="$pStr$ivBin"

	oValue=""
	
	for i in `seq 0 8 $limit`
	do
		byte="${val:$i:8}"
		byteDec=`echo "obase=10;ibase=2; $byte" | bc`
		byteHex=`printf "%02x" $byteDec`
		byteHex="\x$byteHex"
		oValue="$oValue$byteHex"
	done

	oValue=`toUpper $oValue`
	echo $oValue
}	

function getRandomHexString()
{
	length=$1

	rn=""
	for it in `seq 1 $length`
	do
		let "R=$RANDOM%256"
		hexR=`echo "obase=16; ibase=10; $R" | bc`
		rn="$rn\x$hexR"	
	done
	echo $rn
}	

pow() #@ USAGE: pow base exponent
{
   echo $(( ${1:?} ** ${2:?} ))
}

function hexStrToNum()
{
	strng=$1
	type=$2
	
	strng=`echo $strng | tr 'x' ' ' 2>/dev/null`
	strng=`echo $strng | tr '\' ' ' 2>/dev/null`

	res=""
	for ch in $strng
	do
		ch=`echo $ch | tr '[a-z]' '[A-Z]'`
		chBin=`echo "obase=10; ibase=16; $ch" | bc`
		res=$res$ch
	done

	if [ "$type" == "d" ]; then
		echo "obase=10; ibase=16; $res" | bc
	else
		echo $res
	fi
}

function fetchBytes()
{
	fName=$1
	initByte=$2
	numBytes=$3

	let "initByte = initByte + 1"
	contentHex=`od -t x1 -v $fName | awk '{$1=""; print $0}' | tr -d '\n' 2>/dev/null`

	seekValue=""
	for ch in $contentHex
	do
		if [ $numBytes -eq 0 ]; then
			break
		fi
		if [ $initByte -gt 0 ]; then
			let "initByte = initByte - 1"
		fi
		if [ $initByte == 0 ]; then
			let "numBytes = numBytes - 1"
			seekValue="$seekValue $ch"
		fi
	done

	echo $seekValue
}

function bytesToHexString()
{
	input=$1

	hs=""
	for ch in $input
	do
		hs="$hs\x$ch"
	done
	echo $hs
}

function seekByteLoc()
{
	byte=$1
	file=$2

	fContent=`fetchBytes outflow 0 2000`
	
	pos=0
	for ch in $fContent
	do
		let "pos = pos + 1"
		if [ "$ch" == "$byte" ]; then
			break
		fi
	done
	echo $pos
		
}

function h2a()
{
	in=$1

	res=""
	for ch in $in
	do
		ch=`echo $ch | tr '[a-z]' '[A-Z]' 2>/dev/null`
		chBin=`echo "obase=10; ibase=16; $ch" | bc`
		res="$res$chBin"
	done
	echo $res
}

function sendAndRecv() 
{
	msgCode=$1
	senddatah=$2
	packSendSeqh=$3
	clientWriteKeyBytes=$4
	clientHashedMacBytes=$5
	clientReadKeyBytes=$6


	packet="$msgCode$senddatah"

	packetLengthd=`echo -n -e $packet | wc -c`
	let "packetLengthd = packetLengthd + 1"
	packetLengthh=`toHexStr $packetLengthd 4`

	let "paddingLengthd = (8 - (packetLengthd % 8)) + 4"

	let "totalLengthd = packetLengthd + paddingLengthd"

	totalLengthh=`toHexStr $totalLengthd 4`

	paddingLengthh=`toHexStr $paddingLengthd 1`

	pd=""
	let "paddingLengthd = paddingLengthd - 1"
	for it in `seq 0 $paddingLengthd`
	do
       	 	pd=$pd"\x00"
	done

	binaryPacketh="$totalLengthh$paddingLengthh$packet$pd"
	binaryPacketh="$packSendSeqh$binaryPacketh"

	echo -n -e $binaryPacketh > before-encrypt.txt

	binaryPacketCrypt=`echo -n -e $binaryPacketh | openssl enc -e -rc4 -K "$clientWriteKeyBytes"`

	mach=`echo -n -e $binaryPacketCrypt | openssl dgst -binary -hmac "$clientHashedMacBytes" -md5` 

	echo -n -e $binaryPacketCrypt > after-encrypt.txt 
        >outflow
        sleep 1
        echo  -n -e $binaryPacketCrypt$mach | nc localhost 85
        sleep 1

        respb=`cat outflow`
        respCTb=`echo -n -e $respb | openssl enc -d -rc4 -K "$clientReadKeyBytes"`
	echo -n -e $respCTb > receive.txt
	cat receive.txt | hexdump
	

}

function binToHexString()
{
	i=$1

	i=`echo -n -e $i | od -t x1 -v | awk '{$1=""; print}' | tr -d '\n'`

	o=""
	for it in $i
	do
		o=$o"\x$it"
	done

	echo $o
}

###################################################################################################
#
# Clear all previous files
#
###################################################################################################

rm -f inflow
rm -f outflow
rm -f proxypipe


###################################################################################################
#
# Get a cookie string (used during communication further)
#
###################################################################################################


cookieh=`getRandomHexString 16`

###################################################################################################
#
# Kill previous NC processes
#
###################################################################################################

killall -9 nc 2>/dev/null

###################################################################################################
#
# Create a two way pipe
#
###################################################################################################

mknod proxypipe p

###################################################################################################
#
# SSH Message ID
#
###################################################################################################

SSH_MSG_ID="\x14"

###################################################################################################
#
# Redirect whatever is being listened on port 85 to the destination and whatever
# is sent from destination to pipe
#
###################################################################################################

nc -k -l 85 0<proxypipe | tee -a inflow | nc localhost 22 | tee -a outflow 1>proxypipe&
sleep 1

###################################################################################################
#
# Get server version string
#
###################################################################################################

serverVersionBytes=`fetchBytes outflow 0 19`
serverVersionh=`bytesToHexString "$serverVersionBytes"`

###################################################################################################
#
# Create and send client version string to server
# client version stored = Length of client version string + "client version string without \r\n"
# server version stored = Length of server version string + "server version string without \r\n"
#
# Procedure:
# a. Convert client version ascii string to bytes (hex form:  "03 04 05")
# b. Convert bytes to hex string (form: "\x01\x04")
# c. Calculate the length of hex value using echo -n -e <value> | wc -c
# d. Convert the decimal value of the length of hex string in b. 
#    to hex string of the form "\x01\x04"
# 
# same procedure for the server version string
# 
###################################################################################################

clientVersions="SSH-2.0-OpenSSH_5.6"
clientVersionBytes=`echo -n -e $clientVersions | od -t x1 | awk '{$1=""; print}' | tr -d '\n'`
clientVersionh=`bytesToHexString "$clientVersionBytes"`
cvLengthd=`echo -n -e $clientVersionh | wc -c`
cvLengthh=`toHexStr $cvLengthd 4`


svLengthd=`echo -n -e $serverVersionh | wc -c`
svLengthh=`toHexStr $svLengthd 4`

clientVersionNL=$cvLengthh$clientVersionh

serverVersionNL=$svLengthh$serverVersionh


>outflow
> proxypipe
sleep 1
echo -n -e "$clientVersions\r\n" | nc localhost 85
sleep 1

###################################################################################################
#
# server Key Exchange Init packet structure
#
# packet length
# padding length
# key exchange init message code (0x14)
# server Kex Init message
#
# To obtain the size of packet:
# a. search the first 0x14 (ie, the Kex Init Message ID) 
# b. go back by 5 bytes
# 
# Our procedure:
#
# 1. seekByteLoc returns the location of 0x14 in outflow
# 2. Decrement 1 to get the exact location and store that in initByte variable (because 
#    seekByteLoc returns in 1 to x range, but we want the location in 0 - x range)
# 3. Subtract 5 bytes as in step b. above to get the location where the size is stored in hex
# 4. Fill sizeBytes variable witht the int value of the 4 bytes starting from sizeByte returned by 
#    fetchBytes function (fetchBytes returns number of the form ("01 02 03")
# 5. Convert sizeBytes to Hex string (from "01 02 03" to form "\x01\x02\x03")
# 6. Convert the hex string to hex number (ie., from "\x01\x02\x03 to "\x10203")
# 7. Convert the hex number to int (using bc)
# 8. Subtract 6 from the int number (6 == num bytes to represent packet length + 
#    num bytes to represent padding length + num bytes to represent the message code)
#
#    NOTE: Again, during fetchBytes we start from 1 (as earlier), so we have to fetch from the 7th byte
#    (so we subtract 7 instead of 6 from the int number)
#    Again subtract 3 bytes of padding
#
###################################################################################################

initByte=`seekByteLoc '14' outflow`
let "initByte = initByte - 1"
let "sizeByte = initByte - 5"
sizeBytes=`fetchBytes outflow $sizeByte 4`
sizeh=`bytesToHexString "$sizeBytes"`
sizeH=`hexStrToNum $sizeh`
sized=`echo "obase=10; ibase=16; $sizeH" | bc`
let "sized = sized - 6"
let "sized = sized - 1"

###################################################################################################
#
# Now you have the server kex Init message length in sized
# a. Run fetchBytes again from initByte for sized bytes to get the server message into a variable
# b. Convert the bytes (01 02 ab form) to hex string ("\x01\x02\xab" form)
# c. Convert hex string to binary (echo -n -e <hex string>) and store it as the server kex init
#    message in binary form in the variable serverKexb
# d. Convert the size of the server kex init message from decimal (sized) to hex string
# e. Concatenate the length and the server kex init message and store it for later purpose
#
###################################################################################################

let "sized = sized - 3"
serverKexBytes=`fetchBytes outflow $initByte $sized`
serverKexh=`bytesToHexString "$serverKexBytes"`
serverKexb=`echo -n -e $serverKexh`



serverKexSizeh=`toHexStr $sized 4`
serverKexNL="$serverKexSizeh$serverKexh"

###################################################################################################
#
# Client Key Exchange Init packet (message ID = 0x14) is created below
#
# same procedure as above (just reversed here)
#
###################################################################################################

kexAlgStrh="diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1"

kexAlgLend=`echo $kexAlgStrh | wc -c`
let "kexAlgLend=kexAlgLend - 1"
kexAlgLenh=`toHexStr $kexAlgLend 4`

shKeyAlgStrh="ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss"

shKeyAlgLend=`echo $shKeyAlgStrh | wc -c`
let "shKeyAlgLend=shKeyAlgLend - 1"
shKeyAlgLenh=`toHexStr $shKeyAlgLend 4`

encAlgCSh="arcfour,aes128-cbc,aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"

encAlgCSLend=`echo $encAlgCSh | wc -c`
let "encAlgCSLend=encAlgCSLend - 1"
encAlgCSLenh=`toHexStr $encAlgCSLend 4`

encAlgSCh="arcfour,aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se"

encAlgSCLend=`echo $encAlgSCh | wc -c`
let "encAlgSCLend=encAlgSCLend - 1"
encAlgSCLenh=`toHexStr $encAlgSCLend 4`

macAlgCSh="hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"

macAlgCSLend=`echo $macAlgCSh | wc -c`
let "macAlgCSLend=macAlgCSLend - 1"
macAlgCSLenh=`toHexStr $macAlgCSLend 4`

macAlgSCh="hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96"

macAlgSCLend=`echo $macAlgSCh | wc -c`
let "macAlgSCLend=macAlgSCLend - 1"
macAlgSCLenh=`toHexStr $macAlgSCLend 4`

compAlgCSh="none,zlib@openssh.com,zlib"

compAlgCSLend=`echo $compAlgCSh | wc -c`
let "compAlgCSLend=compAlgCSLend -1"
compAlgCSLenh=`toHexStr $compAlgCSLend 4`

compAlgSCh="none,zlib@openssh.com,zlib"

compAlgSCLend=`echo $compAlgSCh | wc -c`
let "compAlgSCLend=compAlgSCLend -1"
compAlgSCLenh=`toHexStr $compAlgSCLend 4`

langCSLenh="\x00\x00\x00\x00"
langSCLenh="\x00\x00\x00\x00"

kexFPFollowsh="\x00"
reservedh="\x00\x00\x00\x00"
paddingh="\x00\x00\x00\x00"
pLenh="\x04"

algorithmsh="$cookieh$kexAlgLenh$kexAlgStrh$shKeyAlgLenh$shKeyAlgStrh$encAlgCSLenh$encAlgCSh$encAlgSCLenh$encAlgSCh$macAlgCSLenh$macAlgCSh$macAlgSCLenh$macAlgSCh$compAlgCSLenh$compAlgCSh$compAlgSCLenh$compAlgSCh$langCSLenh$langSCLenh$kexFPFollowsh$reservedh"

keyExchInith="\x14"

keyExchRecordh="$keyExchInith$algorithmsh$paddingh"

padLenh="\x04"

keyExchRecordh="$padLenh$keyExchRecordh"

pktLend=`echo -n -e $keyExchRecordh | wc -c`
pktLenH=`printf "%d" $pktLend`
pktLenh=`toHexStr $pktLenH 4`

keyExchPkth="$pktLenh$keyExchRecordh"

let "kexLend = pktLend - 5"
kexLenH=`printf "%d" $kexLend`
kexLenh=`toHexStr $kexLenH 4`
clientKexb="$kexLenh$keyExchInith$algorithmsh"
clientKexh=`binToHexString $clientKexb`

clientKexNL=$clientKexh

###################################################################################################
#
# Client Key Exchange Init packet is sent to server here
#
###################################################################################################

sleep 1
echo -n -e $keyExchPkth | nc localhost 85

###################################################################################################
#
# Client Diffie-Hellman GEX Request (Message ID: 0x22) is created and sent to server here
#
###################################################################################################

gexRequestMSGID="\x22"

dhGexMin="\x00\x00\x04\x00"

dhGexNumBits="\x00\x00\x08\x00"

dhGexMax="\x00\x00\x20\x00"

paddingString="\x00\x00\x00\x00\x00\x00"

kexRecord="$gexRequestMSGID$dhGexMin$dhGexNumBits$dhGexMax$paddingString"

paddingLen="\x06"

gexPkt="$paddingLen$kexRecord"

gexPktLen=`echo -n -e "$gexPkt" | wc -c`
gexPktLen=`toHexStr $gexPktLen 4`

gexPktb="$gexPktLen$gexPkt"
gexPkth=`binToHexString $gexPktb`

###################################################################################################
#
# The output from server is cleared here before sending the client DH Gex Request to the server
#
###################################################################################################

>outflow
sleep 1

#
# Sending Client GEX Request to server
#
echo -n -e $gexPktb | nc localhost 85 
sleep 1

###################################################################################################
#
# Identify the position of 0x1f (which is the hex for DH Key Reply message ID in the DH Key 
# Exchange packet returned from server (it contains values of P and G)
#
###################################################################################################

pos=`seekByteLoc "1f" outflow`

###################################################################################################
#
# Fetch 4 bytes from there, and get the message type (doesn't matter)
#
###################################################################################################

msgType=`fetchBytes outflow $pos 4`
msgType=`bytesToHexString "$msgType"`
msgType=`hexStrToNum $msgType d`

###################################################################################################
#
# Fetch 4 bytes from there, and get the length of P
#
###################################################################################################

mpIntLen=`fetchBytes outflow $pos 4`
mpIntLen=`bytesToHexString "$mpIntLen"`
echo $mpIntLen
mpIntLen=`hexStrToNum $mpIntLen d`

###################################################################################################
#
# Position of P is 4 bytes from the length byte
#
###################################################################################################

let "dhPos = pos + 4"

###################################################################################################
#
# Get P, convert it to hex string format ("\x01\x02" and then to binary (echo -n -e <hex string>))
#
###################################################################################################

P=`fetchBytes outflow $dhPos $mpIntLen`
Ph=`bytesToHexString "$P"`
Pb=`echo -n -e $Ph`

###################################################################################################
#
# P is in the form of "0c ad 12 ab ...", which
# should be converted to "0CAD12AB ..."
#
###################################################################################################

Ptemp=""
for it in $P
do
	it=`echo $it | tr '[a-z]' '[A-Z]'`
	iLen=`echo $it | wc -c`
	if [ $iLen -le 2 ]; then
		it="0$it"
	fi
	Ptemp="$Ptemp$it"
done

###################################################################################################
#
# Now converting the P from hex to integer
#
###################################################################################################

Pd=`echo "obase=10; ibase=16; $Ptemp" | bc | tr -d '\' | tr -d '\n'`

###################################################################################################
#
# Position of length byte of G
#
###################################################################################################

let "mpIntLenPos = dhPos + mpIntLen"

###################################################################################################
#
# Length of G
#
###################################################################################################

mpIntLen=`fetchBytes outflow $mpIntLenPos 4`
mpIntLen=`bytesToHexString "$mpIntLen"`
mpIntLen=`hexStrToNum $mpIntLen d`

###################################################################################################
#
# Position of G
#
###################################################################################################

let "dhbPos = mpIntLenPos + 4"

###################################################################################################
#
# Get G
#
###################################################################################################

G=`fetchBytes outflow $dhbPos $mpIntLen`
Gh=`bytesToHexString "$G"`
Gb=`echo -n -e $Gh`

Gtemp=""
for it in $G
do
	it=`echo $it | tr '[a-z]' '[A-Z]'`
	iLen=`echo $it | wc -c`
	if [ $iLen -le 2 ]; then
		it="0$it"
	fi
	Gtemp="$Gtemp$it"
done

Gd=`echo "obase=10; ibase=16; $Gtemp" | bc | tr -d '\' | tr -d '\n'`

###################################################################################################
#
# Identify ((P - 1) / 2) - 1, for getting
# X such that G ^ X is in between 1 and ((P - 1) / 2) - 1
#
###################################################################################################

Plimit=`echo -n -e "$Pd - 1\n" | bc | tr -d '\' |tr -d '\n' 2>/dev/null`
Plimit=`echo -n -e "$Plimit / 2\n" | bc | tr -d '\' |tr -d '\n' 2>/dev/null`
Plimit=`echo -n -e "$Plimit - 1\n" | bc | tr -d '\' |tr -d '\n' 2>/dev/null`

###################################################################################################
#
# Calculate X such that g ^ x mod p is 0 to (p - 1)/2
#
###################################################################################################

Xd=10000

while [ 1 ]
do
	#
	# G ^ X
	#
	GXd=`echo "obase=10; $Gd ^ $Xd" | bc | tr -d '\' |tr -d '\n' 2>/dev/null`

	#
	# E = G ^ X mod P
	#
	Ed=`echo -n -e "$GXd % $Pd\n" | bc | tr -d '\' |tr -d '\n' 2>/dev/null`

	test=`echo -n -e "$Ed < $Plimit\n" | bc`
	if [ $test == 1 ]; then 
		break
	else
		let "Xd = Xd + 10"
	fi
done

###################################################################################################
#
# Create Diffie Hellman GEX Init packet below
#
###################################################################################################

###################################################################################################
#
# Message code
#
###################################################################################################

msgCode="\x20"

###################################################################################################
#
# Padding string
#
###################################################################################################

pString="\x00\x00\x00\x00\x00\x00"

###################################################################################################
#
# Hex value of E (to be sent on network
#
################################################################################################### 

EH=`echo "obase=16; ibase=10; $Ed" | bc | tr -d '\' | tr -d '\n'`
Etemp=`echo $EH | fold -2 | tr '\n' ' '`

ETemp=""
for it in $Etemp
do
	iLen=`echo $it | wc -c`
	if [ $iLen -le 2 ]; then
		it="0$it"
	fi
	ETemp="$ETemp\x$it"
done

Eh=$ETemp

Eb=`echo -n -e $Eh`

###################################################################################################
#
# Now EHex is complete hex string, calculate Length of EHex
#
###################################################################################################

msgCode="\x20"
packet1="$msgCode$Eh"

eLend=`echo -n -e $Eh | wc -c`
eLenh=`toHexStr $eLend 4`

packet2="$msgCode$eLenh$Eh"

packetLengthd=`echo -n -e $packet2 | wc -c`
let "packetLengthd = packetLengthd + 1"
packetLengthh=`toHexStr $packetLengthd 4`

let "paddingLengthd = (8 - (packetLengthd % 8)) + 4"

let "totalLengthd = packetLengthd + paddingLengthd"

totalLengthh=`toHexStr $totalLengthd 4`

paddingLengthh=`toHexStr $paddingLengthd 1`

padding=""
let "paddingLengthd = paddingLengthd - 1"
for it in `seq 0 $paddingLengthd`
do
	padding=$padding"\x00"
done

binaryPacketh="$totalLengthh$paddingLengthh$msgCode$eLenh$Eh$padding"

> outflow

sleep 1
echo -n -e $binaryPacketh | nc localhost 85
sleep 5

###################################################################################################
#
# Now the following values sent from server are there in 
# outflow file:
#
# 1. host key
# 2. f
# 3. signature
# 4. MAC
#
###################################################################################################

posd=`seekByteLoc "3c" outflow`
let "posd = posd + 2"
hkLenBytes=`fetchBytes outflow $posd 4`
hkLenh=`bytesToHexString "$hkLenBytes"`
hkLend=`hexStrToNum $hkLenh d`

let "hkPosd = posd + 4"

hkBytes=`fetchBytes outflow $hkPosd $hkLend`

serverKeyBytes=$hkBytes
serverKeyh=`bytesToHexString "$hkBytes"`

let "mpIntLocd = hkPosd + hkLend"
mpIntLenBytes=`fetchBytes outflow $mpIntLocd 4`
mpIntLenh=`bytesToHexString "$mpIntLenBytes"`
mpIntLend=`hexStrToNum $mpIntLenh d`

let "fLocd = mpIntLocd + 4"

FBytes=`fetchBytes outflow $fLocd $mpIntLend`
Fh=`bytesToHexString "$FBytes"`
Fb=`echo -n -e $Fh`

let "sigLocd = mpIntLocd + mpIntLend"

sigLenBytes=`fetchBytes outflow $sigLocd 4`
sigLenh=`bytesToHexString "$sigLenBytes"`
sigLend=`hexStrToNum $sigLenh d`

let "sigLocd = sigLocd + 8"

sigBytes=`fetchBytes outflow $sigLocd $sigLend`
sigh=`bytesToHexString "$sigBytes"`
sigb=`echo -n -e $sigh`

###################################################################################################
#
# Shared secret is calculated here
#
# Shared secret = K = F ^ X mod P (using a little bit of python here, will change it to bc later)
#
###################################################################################################

FTemp=""
for it in $FBytes
do
	it=`echo $it | tr '[a-z]' '[A-Z]'`
	iLen=`echo $it | wc -c`
	if [ $iLen -le 2 ]; then
		it="0$it"
	fi
	FTemp="$FTemp$it"
done

Fd=`echo "obase=10; ibase=16; $FTemp" | bc | tr -d '\' |tr -d '\n'`
Kd=`echo "print pow(\x00$Fd, $Xd, $Pd)" > /tmp/test.py; python /tmp/test.py`

#
# Terrible error here; sometimes server pre-pends a 0 to the value for whatever reason
#
KH=`echo "obase=16; ibase=10; $Kd" | bc | tr -d '\' | tr -d '\n'`
echo "KH:"$KH

Ktemp=`echo $KH | fold -2 | tr '\n' ' '`
echo "Ktemp:"$Ktemp

Kh=""
for it in $Ktemp
do
	iLen=`echo $it | wc -c`
	if [ $iLen -le 2 ]; then
		it="0$it"
	fi
	Kh="$Kh\x$it"
done

Kb=`echo -n -e $Kh`

skeLengthd=`echo -n -e $serverKeyh | wc -c`
skeLengthh=`toHexStr $skeLengthd 4`
echo $skeLengthh

serverKeyNL=$skeLengthh$serverKeyh


PLd=`echo -n -e $Ph | wc -c`
PLh=`toHexStr $PLd 4`
PNL=$PLh$Ph

GLd=`echo -n -e $Gh | wc -c`
GLh=`toHexStr $GLd 4`
echo $GLh
GNL=$GLh$Gh

ELd=`echo -n -e $Eh | wc -c`
ELh=`toHexStr $ELd 4`
ENL=$ELh$Eh

FLd=`echo -n -e $Fh | wc -c`
FLh=`toHexStr $FLd 4`
FNL=$FLh$Fh

KLd=`echo -n -e $Kh | wc -c`
echo "KLd:"$KLd
KLh=`toHexStr $KLd 4`
KNL=$KLh$Kh


echo "CLIENTVERSION:"$clientVersionNL
echo "SERVERVERSION:"$serverVersionNL
echo "CLIENTKEX:"$clientKexNL
echo "SERVERKEX:"$serverKexNL
echo "SERVERKEY:"$serverKeyNL

echo "P:"$PNL
echo "G:"$GNL
echo "E:"$ENL
echo "F:"$FNL
echo "K:"$KNL


length="\x00\x00\x04\x00\x00\x00\x08\x00\x00\x00\x20\x00"

skMaterialh="$clientVersionNL$serverVersionNL$clientKexNL$serverKexNL$serverKeyNL$length$PNL$GNL$ENL$FNL$KNL"

echo -n -e "Key material:\r\n"
echo $skMaterialh
sKeyb=`echo -n -e $skMaterialh | openssl dgst -sha256 -binary`
echo $sKeyb

sKeyh=`binToHexString "$sKeyb"`
echo "Shared secret:$sKeyh"


A="\x43"
B="\x44"
C="\x45"
D="\x46"
E="\x47"
F="\x48"

# cwMaterialh=$KNL$sKeyh$C$sKeyh
cwMaterialh=$KNL$sKeyh$C$cookieh
clientWriteKeyb=`echo -n -e $cwMaterialh | openssl dgst -sha1 -binary`
clientWriteKeyh=`binToHexString "$clientWriteKeyb"`
echo "Client Write Key:"$clientWriteKeyh
clientWriteKeyBytes=`echo "$clientWriteKeyh" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32 |fold -2`
clientWriteKeyBytes1=`echo "$clientWriteKeyh" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32`
clientWriteKeyh=`bytesToHexString "$clientWriteKeyBytes"`
echo "Client Write Key:"$clientWriteKeyh

# crMaterialh=$KNL$sKeyh$D$sKeyh
crMaterialh=$KNL$sKeyh$D$cookieh
clientReadKeyb=`echo -n -e $crMaterialh | openssl dgst -sha1 -binary`
clientReadKeyh=`binToHexString "$clientReadKeyb"`
clientReadKeyBytes=`echo "$clientReadKeyh" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32 |  fold -2`
clientReadKeyBytes1=`echo "$clientReadKeyh" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32`
clientReadKeyh=`bytesToHexString "$clientReadKeyBytes"`
echo "Client Read Key:"$clientReadKeyh

# chmMaterialh=$KNL$sKeyh$E$sKeyh
chmMaterialh=$KNL$sKeyh$E$cookieh
clientHashedMacb=`echo -n -e $chmMaterialh | openssl dgst -sha1 -binary`
clientHashedMach=`binToHexString "$clientHashedMacb"`
clientHashedMacBytes=`echo "$clientHashedMach" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32 | fold -2`
clientHashedMacBytes1=`echo "$clientHashedMach" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32`
clientHashedMach=`bytesToHexString "$clientHashedMacBytes"`
echo "Client Hasahed MAC:"$clientHashedMach

# shmMaterialh=$KNL$sKeyh$F$sKeyh
shmMaterialh=$KNL$sKeyh$F$cookieh
serverHashedMacb=`echo -n -e $shmMaterialh | openssl dgst -sha1 -binary`
serverHashedMach=`binToHexString "$serverHashedMacb"`
serverHashedMacBytes=`echo "$serverHashedMach" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32 | fold -2`
serverHashedMacBytes1=`echo "$serverHashedMach" | fold -4 | sed 's/\\x//g' | tr -d '\n' | tr -d '\\' | cut -c -32`
serverHashedMach=`bytesToHexString "$serverHashedMacBytes"`
echo "Server Hashed MAC:"$serverHashedMach


clientNewKeysMsgh="\x00\x00\x00\x0C\x0A\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"

###################################################################################################
#
# send Client NewKeys message to server here after clearing outflow
#
###################################################################################################

>outflow
sleep 1
echo -n -e $clientNewKeysMsgh | nc localhost 85
sleep 1

###################################################################################################
#
# Handshake completed here
#
# First encrypted packet sent from below
#
###################################################################################################

msgCode="\x05"
senddatah="\x73\x73\x68\x2d\x75\x73\x65\x72\x61\x75\x74\x68"
packSendSeqh="\x00\x00\x00\x01"

sendAndRecv $msgCode $senddatah $packSendSeqh $clientWriteKeyBytes $clientHashedMacBytes $clientReadKeyBytes

